package org.mifos.boss.business.helper;

import java.sql.Date;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.mifos.boss.definitions.customerregistration.AddressType;
import org.mifos.boss.definitions.customerregistration.ClientCreationalDetailType;
import org.mifos.boss.definitions.customerregistration.ClientFamilyDetailType;
import org.mifos.boss.definitions.customerregistration.ClientNameDetailType;
import org.mifos.boss.definitions.customerregistration.ClientPersonalDetailType;
import org.mifos.boss.definitions.customerregistration.Mobile2BossDataExchange;
import org.mifos.boss.domainmodel.Address;
import org.mifos.boss.domainmodel.ApplicableAccountFeeType;
import org.mifos.boss.domainmodel.ClientCreationalData;
import org.mifos.boss.domainmodel.ClientFamilyDetails;
import org.mifos.boss.domainmodel.ClientNameDetails;
import org.mifos.boss.domainmodel.ClientPersonalDetails;
import org.mifos.boss.domainmodel.Mobile2BossData;
import org.mifos.boss.domainmodel.SavingProducts;
import org.mifos.boss.domainmodel.constants.TransferStatusEnum;
import org.springframework.stereotype.Repository;

/**
 * This utility is placeholder for XML unmarshalled/marshalled Definition objects to 
 * domain Model objects, which can be used in hibernate
 */
@Repository(value="mobile2BossDataMapper")
public class BossDefinitionsToDomainObjectMapper {

	public Mobile2BossData transform(Mobile2BossDataExchange mobileDefinition){
		Mobile2BossData mobileData = new Mobile2BossData();
		mobileData.setDeviceId(mobileDefinition.getDeviceId());
		mobileData.setTransferStatus(TransferStatusEnum.READY.getValue()); 
		mobileData.setTransferTimeStamp(new Timestamp(System.currentTimeMillis()));
		mobileData.setClientCreationalData(getClientCreationalDataAfterMapping(mobileDefinition.getClientCreationalType()));
		return mobileData;
	}

	private List<ClientCreationalData> getClientCreationalDataAfterMapping(
			List<ClientCreationalDetailType> clientCreationalTypeList) {
		List<ClientCreationalData> clientCreationalDataList = new ArrayList<ClientCreationalData>();
		for (ClientCreationalDetailType clientCreationalType:clientCreationalTypeList){
			clientCreationalDataList.add(getClientCreationalDataMapped(clientCreationalType));
		}
		return clientCreationalDataList;
	}

	private ClientCreationalData getClientCreationalDataMapped(
			ClientCreationalDetailType clientCreationalType) {
		ClientCreationalData clientCreationalData = new ClientCreationalData();
		
		if(clientCreationalType.getActivationDate() != null)
			clientCreationalData.setActivationDate(new Date(clientCreationalType.getActivationDate().toGregorianCalendar().getTimeInMillis()));
		clientCreationalData.setClientName(clientCreationalType.getClientName());
		clientCreationalData.setClientStatus(clientCreationalType.getClientStatus());
		if(clientCreationalType.getDateofbirth() != null)
			clientCreationalData.setDateOfBirth(new Date(clientCreationalType.getDateofbirth().toGregorianCalendar().getTimeInMillis()));
		clientCreationalData.setExternalId(clientCreationalType.getExternalId());
		clientCreationalData.setFormedBy(clientCreationalType.getFormedBy());
		clientCreationalData.setGovernmentId(clientCreationalType.getGovernmentId());
		clientCreationalData.setGroupFlag(clientCreationalType.getGroupflag());
		//::TODO:: Missing table entry
		//clientCreationalData.setIstrained(clientCreationalType.getTrainedDate());
		clientCreationalData.setLoanOfficerId(clientCreationalType.getLoanOfficerId());
		clientCreationalData.setMfiJoiningDate(new Date(clientCreationalType.getMfiJoiningDate().toGregorianCalendar().getTimeInMillis()));
		clientCreationalData.setParentGroupId(clientCreationalType.getParentGroupId());
		clientCreationalData.setTainingDate(new Date(clientCreationalType.getTrainedDate().toGregorianCalendar().getTimeInMillis()));
		//::TODO:: make sure this value is populated when info is received from mifos
		//clientCreationalData.setTempCustId(clientCreationalType.get);
		//::TODO:: generate in boss
		//clientCreationalData.setTransferId(clientCreationalType.get);
		clientCreationalData.setAddress(transformAddress(clientCreationalType.getAddress()));
		clientCreationalData.setApplicableAccountType(transformApplicableAccountType(clientCreationalType.getApplicableAccountFee()));
		clientCreationalData.setClientFamilyDetails(transformClientFamilyDetails(clientCreationalType.getFamilyDetails()));
		
		//clientCreationalData.setClientNameDetail(transformClientNameDetail(clientCreationalType.getClientNameDetail()));
		clientCreationalData.setSavingProducts(transformSavingProducts(clientCreationalType.getSelectedSavingProducts()));
		clientCreationalData.setClientPersonalDetails(transformClientPersonalDetails(clientCreationalType.getClientPersonalDetail()));
		return clientCreationalData;
	}

	private ClientPersonalDetails transformClientPersonalDetails(ClientPersonalDetailType clientPersonalDetail) {
		ClientPersonalDetails clientPersonalDetails = new ClientPersonalDetails();
		clientPersonalDetails.setBusinessActivities(clientPersonalDetail.getBusinessActivities().intValue());
		//::TODO:: need to populate the rest of the values
		return clientPersonalDetails;
	}

	private List<SavingProducts> transformSavingProducts(
			List<Short> selectedSavingProducts) {
		List<SavingProducts> savingProducts = new ArrayList<SavingProducts>();
		for(Short savingProductId:selectedSavingProducts){
			SavingProducts savingProd = new SavingProducts();
			savingProd.setProductId(savingProductId);
		}
		return savingProducts;
	}

	private ClientNameDetails transformClientNameDetail(ClientNameDetailType clientNameDetail) {
		ClientNameDetails cName = new ClientNameDetails();
		cName.setFirstname(clientNameDetail.getFirstname());
		cName.setLastname(clientNameDetail.getLastname());
		cName.setMiddlename(clientNameDetail.getMiddlename());
		cName.setNameType(clientNameDetail.getNameType());
		cName.setSalutation(clientNameDetail.getSalutation().intValue());
		cName.setSecondLastname(clientNameDetail.getSecondLastname());
		
		return cName;
	}



	private List<ClientFamilyDetails> transformClientFamilyDetails(
			List<ClientFamilyDetailType> familyDetailsList) {
		// TODO Auto-generated method stub
			List<ClientFamilyDetails> clientFamilyDetails = new ArrayList<ClientFamilyDetails>();
			
			for(ClientFamilyDetailType cFamilyDetail: familyDetailsList){
				ClientFamilyDetails cFDetail = new ClientFamilyDetails();
			
				cFDetail.setDateOfBirth(new Date(cFamilyDetail.getDateOfBirth().toGregorianCalendar().getTimeInMillis()));
				cFDetail.setDisplayName(cFamilyDetail.getDisplayName());
				cFDetail.setGender(cFamilyDetail.getGender());
				cFDetail.setLivingsatus(cFamilyDetail.getLivingStatus());
				cFDetail.setRelationship(cFamilyDetail.getRelationship());
				
				clientFamilyDetails.add(cFDetail);
			}
		
		return clientFamilyDetails;
	}

	private List<ApplicableAccountFeeType> transformApplicableAccountType(
			List<org.mifos.boss.definitions.customerregistration.ApplicableAccountFeeType> applicableAccountFeeList) {
		// TODO Auto-generated method stub
		List<ApplicableAccountFeeType> appAccountFee = new ArrayList<ApplicableAccountFeeType>();
		
		for(org.mifos.boss.definitions.customerregistration.ApplicableAccountFeeType appFee:applicableAccountFeeList){
			ApplicableAccountFeeType fee = new ApplicableAccountFeeType();
			
			fee.setAmount(appFee.getAmount());
			fee.setFeeID(appFee.getFeeID().intValue());
			fee.setFeeName(appFee.getFeeName());
			fee.setFeeSchedule(appFee.getFeeSchedule());
			fee.setMonthly(appFee.isMonthly());
			fee.setPeriodic(appFee.isPeriodic());
			fee.setWeekly(appFee.isWeekly());
			fee.setRemoved(appFee.isRemoved());	
			
			appAccountFee.add(fee);
		}
			
		return appAccountFee;
	}

	private Address transformAddress(AddressType address) {
		// TODO Auto-generated method stub
		Address transformedAddress = new Address();
		transformedAddress.setLine1(address.getLine1());
		transformedAddress.setLine1(address.getLine2());
		transformedAddress.setLine1(address.getLine3());
		transformedAddress.setLine1(address.getCity());
		transformedAddress.setLine1(address.getCountry());
		transformedAddress.setLine1(address.getState());
		transformedAddress.setLine1(address.getPhoneNumber());
		transformedAddress.setLine1(address.getZip());
		
		return transformedAddress;
	}
}
